#ifndef  FRAME_CLIENT_H
#define  FRAME_CLIENT_H

#include <unordered_map>
#include "Interface.h" // for IClient
#include "Util.h"

namespace frame {

class IChannelHandlerAdapter ;
class IChannel;

class ImplFactory;
class ClientImpl;
class ConnectHandler;
class ChannelHandler;
class Client : public IClient , public std::enable_shared_from_this<Client> {
public:
    Client(IService::Ptr service, IChannelHandlerAdapter::Ptr defaultChannelHandlerAdapter);
    ~Client() override;

    bool isOpen() override{
        return opened;
    }
    int open() override;
    void close() override;

    uint64_t getId() const override {
        return id;
    }
    void setId(const uint64_t id)override{
        this->id = id;
    }

    IChannelHandlerAdapter::Ptr getDefaultChannelHandlerAdapter() override{
        return defaultChannelHandlerAdapter;
    }

    IChannel::Ptr connect(const std::string & remoteIp, const int remotePort, IChannelHandlerAdapter::Ptr channelHandler) override;
    int broadcast(const char * buffer, size_t len);

public:
    uint64_t add(IChannel::Ptr channel) override;
    void remove(uint64_t id) override;
    IChannel::Ptr get(uint64_t id) override;
    size_t size() override;

private:
    std::shared_ptr<IService> getService() {
        return service.lock();
    }
private:
    std::shared_ptr<ImplFactory> factory;
    std::shared_ptr<ClientImpl> impl; 

    uint64_t id;
    std::weak_ptr<IService> service; // client not owne of service 
    IChannelHandlerAdapter::Ptr defaultChannelHandlerAdapter;
    bool opened;

    std::unordered_map<uint64_t, IChannel::Ptr> channelMap; //add in connected, remove when disconnected
    UniqueNumber numbers;
    std::shared_ptr<ConnectHandler> connectHandler;
    std::shared_ptr<ChannelHandler> channelHandler;
};

} //end of namespace frame

#endif   /* FRAME_CLIENT_H */
